﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using io = System.IO;
using wf = System.Windows.Forms;
using dw = System.Drawing;

namespace editor.app
{
    /// <summary>
    /// RImage.xaml 的交互逻辑
    /// </summary>
    public partial class RImage : UserControl, IResEditControl
    {
        public static Canvas GetFrameCanvas(comm.objst.RPack rpack, string rimageResKey, int frameIndex, BitmapImage bitmap = null)
        {
            var cv = new Canvas();
            var rimage = rpack.GetResource<comm.objst.RImage>(rimageResKey);
            if (rimage != null)
            {
                var frame = rimage.GetFrame(frameIndex);
                if (frame != null)
                {
                    cv.Width = frame.Width;
                    cv.Height = frame.Height;
                    cv.Clip = new RectangleGeometry(new Rect(0, 0, frame.Width, frame.Height));
                    if (bitmap == null)
                    {
                        bitmap = new BitmapImage();
                        if (rimage.ImageBytes != null)
                        {
                            bitmap.FromBytes(rimage.ImageBytes);
                        }
                    }
                    var image = new Image
                    {
                        Source = bitmap,
                        Width = bitmap.PixelWidth,
                        Height = bitmap.PixelHeight
                    };
                    image.SetLeftTop(-frame.X, -frame.Y);
                    cv.Children.Add(image);

                    var CENTRE_DOT_SIZE = 9;
                    var dot = new Ellipse
                    {
                        Opacity = .6,
                        Width = CENTRE_DOT_SIZE,
                        Height = CENTRE_DOT_SIZE,
                        Fill = new SolidColorBrush(Color2.Red()),
                        Stroke = new SolidColorBrush(Color2.White()),
                        StrokeThickness = 1
                    };
                    dot.SetLeftTop(frame.CentreX - CENTRE_DOT_SIZE / 2, frame.CentreY - CENTRE_DOT_SIZE / 2);
                    cv.Children.Add(dot);
                }
            }
            return cv;
        }

        comm.objst.RPack _rpack = null;
        comm.objst.RImage _rimage = null;
        string _imageResKey = "";

        public RImage(comm.objst.RPack rpack, string imageResKey)
        {
            InitializeComponent();

            _imageResKey = imageResKey;
            _rpack = rpack;
            _rimage = _rpack.GetResource<comm.objst.RImage>(imageResKey);
            imageView.OnClickFrameCalback = ClickFrame;

            Fill();

            btnSetImage.Click += new RoutedEventHandler(btnSetImage_Click);
            btnClearFrames.Click += new RoutedEventHandler(btnClearFrames_Click);
            btnMakeFramesFromRowCol.Click += new RoutedEventHandler(btnMakeFramesFromRowCol_Click);
            btnMakeFramesFromWH.Click += new RoutedEventHandler(btnMakeFramesFromWH_Click);
            btnAddFrame.Click += new RoutedEventHandler(btnAddFrame_Click);
            btnEditFrames.Click += new RoutedEventHandler(btnEditFrames_Click);
            tbWH.KeyDown += new KeyEventHandler(tbWH_KeyDown);
            tbRC.KeyDown += new KeyEventHandler(tbRC_KeyDown);
            tbRect.KeyDown += new KeyEventHandler(tbRect_KeyDown);
            btnSplice.Click += new RoutedEventHandler(btnSplice_Click);
        }

        void btnSplice_Click(object sender, RoutedEventArgs e)
        {
            var w = new ImageSplice(this, _rpack) { Width = 800, Height = 600, ShowInTaskbar = false };
            w.ShowDialog();
            Fill();
        }
        void tbRect_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                btnAddFrame_Click(btnAddFrame, new RoutedEventArgs());
            }
        }
        void tbRC_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                btnMakeFramesFromRowCol_Click(btnMakeFramesFromRowCol, new RoutedEventArgs());
            }
        }
        void tbWH_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                btnMakeFramesFromWH_Click(btnMakeFramesFromWH, new RoutedEventArgs());
            }
        }
        void btnClearFrames_Click(object sender, RoutedEventArgs e)
        {
            _rimage.FrameList.Clear();
            Fill();
        }
        void btnMakeFramesFromWH_Click(object sender, RoutedEventArgs e)
        {
            int w = 0, h = 0;
            var ss = tbWH.Text.Split(',');
            if (ss.Length == 2 && int.TryParse(ss[0].Trim(), out w) && int.TryParse(ss[1].Trim(), out h))
            {
                var wc = (int)Math.Ceiling(_rimage.Width / (double)w);
                var hc = (int)Math.Ceiling(_rimage.Height / (double)h);

                _rimage.FrameList.Clear();
                _rimage.FrameList.Add(new comm.objst.RImage.Frame
                {
                    X = 0,
                    Y = 0,
                    Width = _rimage.Width,
                    Height = _rimage.Height
                });
                for (int x = 0; x < wc; x++)
                {
                    for (int y = 0; y < hc; y++)
                    {
                        _rimage.FrameList.Add(new comm.objst.RImage.Frame
                        {
                            X = x * w,
                            Y = y * h,
                            Width = w,
                            Height = h
                        });
                    }
                }
                Fill();
            }
        }
        void btnMakeFramesFromRowCol_Click(object sender, RoutedEventArgs e)
        {
            int row = 0, col = 0;
            var ss = tbRC.Text.Split(',');
            if (ss.Length == 2 && int.TryParse(ss[0].Trim(), out row) && int.TryParse(ss[1].Trim(), out col))
            {
                var cw = (int)Math.Ceiling(_rimage.Width / (double)col);
                var ch = (int)Math.Ceiling(_rimage.Height / (double)row);

                _rimage.FrameList.Clear();
                _rimage.FrameList.Add(new comm.objst.RImage.Frame
                {
                    X = 0,
                    Y = 0,
                    Width = _rimage.Width,
                    Height = _rimage.Height
                });
                for (int x = 0; x < col; x++)
                {
                    for (int y = 0; y < row; y++)
                    {
                        _rimage.FrameList.Add(new comm.objst.RImage.Frame
                        {
                            X = x * cw,
                            Y = y * ch,
                            Width = cw,
                            Height = ch
                        });
                    }
                }
                Fill();
            }
        }
        void btnAddFrame_Click(object sender, RoutedEventArgs e)
        {
            int x = 0, y = 0, w = 0, h = 0;
            var ss = tbRect.Text.Split(',');
            if (ss.Length == 4 &&
                int.TryParse(ss[0].Trim(), out x) &&
                int.TryParse(ss[1].Trim(), out y) &&
                int.TryParse(ss[2].Trim(), out w) &&
                int.TryParse(ss[3].Trim(), out h))
            {
                _rimage.FrameList.Add(new comm.objst.RImage.Frame
                {
                    X = x,
                    Y = y,
                    Width = w,
                    Height = h
                });
                Fill();
            }
        }
        void btnSetImage_Click(object sender, RoutedEventArgs e)
        {
            var ofd = new wf.OpenFileDialog();
            if (ofd.ShowDialog().ToString() == "OK")
            {
                try
                {
                    using (var ms = new io.MemoryStream(io.File.ReadAllBytes(ofd.FileName)))
                    {
                        var bitmap = dw.Bitmap.FromStream(ms);
                        using (var saveMs = new io.MemoryStream())
                        {
                            bitmap.Save(saveMs, dw.Imaging.ImageFormat.Png);
                            _rimage.ImageBytes = saveMs.ToArray();
                            _rimage.Width = bitmap.Width;
                            _rimage.Height = bitmap.Height;
                            Fill();
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }
        void btnEditFrames_Click(object sender, RoutedEventArgs e)
        {
            var sb = new StringBuilder();
            var ix = 0;
            foreach (var frame in _rimage.FrameList)
            {
                sb.Append("/*" + ix.ToString("D4") + "*/" + comm.JsonSerializer.Serialize(frame) + ",\n");
                ix++;
            }
            if (sb.Length > 0)
            {
                sb.Remove(sb.Length - 2, 2);
            }
            var window = new TextWindow { Width = 800, Height = 600 };
            window.InputText = sb.ToString();
            window.ShowDialog();

            try
            {
                var frameList = comm.JsonSerializer.Deserialize<List<comm.objst.RImage.Frame>>("[" + window.InputText + "]");
                if (frameList != null)
                {
                    _rimage.FrameList = frameList;
                    Fill();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        void ClickFrame(int frameIndex, int x, int y)
        {
            var frame = _rimage.FrameList[frameIndex];
            frame.CentreX = x;
            frame.CentreY = y;
            if (ckCentreSync.IsChecked == true)
            {
                foreach (var item in _rimage.FrameList)
                {
                    if (item.Width == frame.Width && item.Height == frame.Height)
                    {
                        item.CentreX = x;
                        item.CentreY = y;
                    }
                }
                var keys = _rpack.GetAllResourceKeys(typeof(comm.objst.RImage));
                foreach (var key in keys)
                {
                    var rImage = _rpack.GetResource<comm.objst.RImage>(key);
                    if (key != _imageResKey && FindTag(_rimage.Tag, rImage.Tag))
                    {
                        foreach (var item in rImage.FrameList)
                        {
                            if (item.Width == frame.Width && item.Height == frame.Height)
                            {
                                item.CentreX = x;
                                item.CentreY = y;
                            }
                        }
                    }
                }
            }
            Fill();
        }
        bool FindTag(string tag1, string tag2)
        {
            var ss = tag1.Split(',');
            foreach (var s in ss)
            {
                if (tag2.IndexOf(s) != -1)
                {
                    return true;
                }
            }
            return false;
        }

        void Fill()
        {
            if (_rimage.ImageBytes != null)
            {
                imageView.Load(_rpack, _imageResKey);
                tbSize.Text = _rimage.Width + "x" + _rimage.Height + " frames(" + _rimage.FrameList.Count + ")";
            }
        }

        public void Reload()
        {
            Fill();
        }
        public string GetResKey()
        {
            return _imageResKey;
        }
    }
}
